'abuinput.monkey by Belimoth

'TODO
'	multiple bindings for the same action
'	timeline
'	number of hits within a given window
'	integration with abureplay

Strict
Import mojo
Import abutime



Class Input

Public
	Global unit:Int = UNIT_MILLISECONDS		'not implemented yet
	
	Function Bind:Void(action:String, keyCode:Int)
		Local bindingNew := New Binding(action, keyCode)
		bindings.Set(action, bindingNew)
	End
	
	Function Down:Bool(action:String)
		Return bindings.Get(action).Down()
	End
	
	Function Up:Bool(action:String)
		Return bindings.Get(action).Up()
	End
	
	Function Hit:Bool(action:String, timeWindow:Int = 0)
		Return bindings.Get(action).Hit(timeWindow)
	End
	
	Function Release:Bool(action:String, timeWindow:Int = 0)
		Return bindings.Get(action).Release(timeWindow)
	End
	
Private
	Global bindings := New StringMap<Binding>
	'Global queue := New ListQueue<InputEvent>()						not sure if this is how to do it
	
	Function Update:Void()
		For Local binding := Eachin bindings.Values()
			binding.Update()
		Next
	End
End



Function InputDown:Bool(action:String)							Return Input.Down(action)					End
Function InputUp:Bool(action:String)							Return Input.Up(action)						End
Function InputHit:Bool(action:String, timeWindow:Int = 0)		Return Input.Hit(action, timeWindow)		End
Function InputRelease:Bool(action:String, timeWindow:Int = 0)	Return Input.Release(action, timeWindow)	End



Function UpdateInput:Void()
	Input.Update()
End



Private

Class Binding
	Field action:String
	Field keyCode:Int
	
	Field state:Bool
	Field statePrevious:Bool
	Field hit:Bool, release:Bool
	Field hits:Int				'not used yet
	Field lastHit:Int			'not implemented
	Field lastRelease:Int		'not implemented
	
	Method New(action:String, keyCode:Int)
		Self.action = action
		Self.keyCode = keyCode
	End
	
	Method Update:Void()
		statePrevious = state
		state = ( KeyDown(keyCode) = 1 )		'sketchy
		hits = KeyHit(keyCode)
		
		hit = False
		release = False
		
		If KeyHit(keyCode)
			hit = True
			lastHit = CurrentTime()
		EndIf
		
		'If KeyHit(keyCode) And Not KeyDown(keyCode) Then Print "mismatch"
		
		If statePrevious And Not(state)
			release = True
			lastRelease = CurrentTime()
		Endif
	End
	
	Method Down:Bool()		Return state End
	
	Method Up:Bool()		Return Not(state) End
	
	Method Hit:Bool(timeWindow:Int = 0)
		If timeWindow = 0 Then Return hit
		Return (CurrentTime() - lastHit <= timeWindow)
	End
	
	Method Release:Bool(timeWindow:Int = 0)
		If timeWindow = 0 Then Return release
		Return (CurrentTime() - lastRelease <= timeWindow)
	End
End